﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyDelegateDemo.MyObserver
{
    /// <summary>
    /// 故事：
    /// 夜黑风高的夜里：
    /// 一只猫Miao了下，紧接着触发了一系列的行为
    /// 1、小孩儿哭了
    /// 2、狗叫了
    /// 3、哥哥也醒了
    /// 4、妈妈起床了
    /// 5、。。。。。。 后面这里还有一些动作~~
    /// 
    /// 要求：以OOP思想来完成~~
    /// 
    /// 请问：
    /// 代码这样写好吗？如果让你们来写你们会这样写吗？
    /// 1、猫不纯粹---逻辑耦合太重，在猫身上写了写不属于猫的行为，依赖太重；--修改其他类，导致猫不稳定
    /// 2、如果想要修改下执行顺序呢，猫也要修改；
    /// 3、猫很不稳定
    /// 
    /// 应该如何改？
    /// 目标：
    /// 猫要足够纯粹，猫只Miao一声~~
    /// Miao一声之后的行为，不写入在猫的身上，可以对外开发一个盒子，让外面向这个盒子中添加行为。
    ///  
    /// 技术上来说：多播委托的应用：
    /// 把一些的行为对外暴露委托，让外部来+=逻辑；
    /// 代码更加稳定；
    /// 
    /// 职责的单一性~   设计模式原则的第一原则；
    /// 降低了耦合
    /// 
    /// ----大名鼎鼎的观察者模式~~
    /// </summary>
    public class Cat
    {
        public void Miao()
        {
            Console.WriteLine($"{GetType().Name} Miao 一声~~");
            new Baby().Cry();
            new Dog().Wang();
            new Brother().Turn();
            new Mother().Whisper();
            new Father().Roar();
        }
         
        public Action ActionHander;  
        public void MiaoHandler()
        {
            Console.WriteLine($"{GetType().Name} MiaoHandler 一声~~");
            //if (ActionHander!=null)
            //{
            //    ActionHander.Invoke();
            //} 
            ActionHander?.Invoke();
        }


        //上面【委托的实现】和下面【OOP实现】 二者有什么区别？
        //委托更简洁~~
        //上面的实现思想：通过委托装方法----委托的本质--类====类封装多个方法，在需要的时候，直接执行逻辑；
        //
        //下面的实现思想：通过集合装对象----结合的本质--泛型类===类中封装对象，在需要的时候执行对象中的方法

        /// <summary>
        /// 定义了集合，保存接口
        /// </summary>
        public List<IObserver> ObserverList=new List<IObserver>(); 
        public void MiaoObserver()
        {
            Console.WriteLine($"{GetType().Name} MiaoObserver 一声~~");
            foreach (var observer in ObserverList)
            {
                observer.Action();
            }

            //Tuple<int, int> tuple = new Tuple<int, int>(123,234);
            //(int, int) tun = new (int, int)(123,234);  //具体去看看C#语法
        }
    }
}
